#include <cstdio>
#include <systemc>

using namespace sc_core;
using namespace sc_dt;

// [定义 HalfAdder 模块]
SC_MODULE(HalfAdder) {
    // [声明端口]
    sc_in<bool>     a;
    sc_in<bool>     b;
    sc_out<bool>    s;
    sc_out<bool>    c;

    // [逻辑处理函数]
    void process_logic() {
        s.write(a.read() ^ b.read());
        c.write(a.read() & b.read());
    }

    // [构造函数]
    SC_CTOR(HalfAdder) {
        // [注册进程]: 注册 process_logic 为一个 SC_METHOD 进程
        SC_METHOD(process_logic);
        // [定义敏感列表]: 当输入 a 或 b 变化时, 执行 process_logic
        sensitive << a << b;
    }
};

// [定义 FullAdder 模块]
SC_MODULE(FullAdder) {
    // [声明端口]
    sc_in<bool>     a;
    sc_in<bool>     b;
    sc_in<bool>     ci;
    sc_out<bool>    s;
    sc_out<bool>    co;

    // [内部信号]
    sc_signal<bool> s1, c1, c2;

    // [HalfAdder 模块]
    HalfAdder ha1;
    HalfAdder ha2;

    // [逻辑处理函数]
    void or_logic() {
        co.write(c1.read() | c2.read());
    }

    // [构造函数]
    SC_CTOR(FullAdder): ha1("ha1"), ha2("ha2") {

        // [绑定端口]
        ha1.a(a);
        ha1.b(b);
        ha1.s(s1);
        ha1.c(c1);
        // ha1(a, b, s1, c1);

        ha2.a(s1);
        ha2.b(ci);
        ha2.s(s);
        ha2.c(c2);
        // ha2(s1, ci, s, c2);

        // [注册进程]
        SC_METHOD(or_logic);

        // [定义敏感列表]
        sensitive << c1 << c2;
    }
};

// [定义 Driver 模块]
SC_MODULE(Driver) {
    // [声明端口]
    sc_out<bool> a, b, ci;

    // [构造函数]
    SC_CTOR(Driver) {
        // [注册进程]
        SC_THREAD(drive_thread);
    }

    // [驱动函数]
    void drive_thread() {
        sc_uint<3> pattern = 0;
        while (true) {
            a.write(pattern[0]);
            b.write(pattern[1]);
            ci.write(pattern[2]);
            wait(10, SC_NS);
            pattern++;
        }
    }
};

// [定义 Monitor 模块]
SC_MODULE(Monitor) {
    // [声明端口]
    sc_in<bool> a, b, ci, s, co;

    // 波形文件
    sc_trace_file* tf;

    // [采样函数]
    void sample_thread() {
        wait(5, SC_NS);
        printf("a  b  ci s  co | Time\n");
        printf("-------------------------\n");
        while (true) {
            printf("%d  %d  %d  %d  %d  | %s\n", 
                a.read(), b.read(), ci.read(), s.read(), co.read(), 
                sc_time_stamp().to_string().c_str()
            );
            wait(10, SC_NS); // 等待10ns到下一个采样点
        }
    }

    // [构造函数]
    SC_CTOR(Monitor) {
        // [注册采样进程]
        SC_THREAD(sample_thread);

        // [波形追踪]
        tf = sc_create_vcd_trace_file("full_adder");
        tf->set_time_unit(1, SC_NS);
        sc_trace(tf, a, "a");
        sc_trace(tf, b, "b");
        sc_trace(tf, ci, "ci");
        sc_trace(tf, s, "s");
        sc_trace(tf, co, "co");
    }

    // [析构函数]
    ~Monitor() {
        sc_close_vcd_trace_file(tf);
    }
}; 

int  sc_main(int argc, char* argv[]) {
    // [声明信号]: 用于连接模块端口
    sc_signal<bool> a, b, ci, s, co;

    // [实例化 FullAdder 模块]
    FullAdder full_adder("full_adder");

    // [绑定端口]: 将信号连接到模块的端口
    full_adder.a(a);
    full_adder.b(b);
    full_adder.ci(ci);
    full_adder.s(s);
    full_adder.co(co);

    // [实例化 Driver 模块]: 施加激励
    Driver driver("driver");
    driver.a(a);
    driver.b(b);
    driver.ci(ci);

    // [实例化 Monitor 模块]: 监控输出
    Monitor monitor("monitor");
    monitor.a(a);
    monitor.b(b);
    monitor.ci(ci);
    monitor.s(s);
    monitor.co(co);

    // [开始仿真]
    sc_start(100, SC_NS);

    return 0;
}
